package com.lzw.DailyAudit.service.issueReports_04;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.excel.EasyExcel;
import com.hooya.fa.eu.biz.DailyAudit.entity.dto.StockListDTO;
import com.hooya.fa.eu.biz.DailyAudit.entity.dto.StockListExcelDTO;
import com.hooya.fa.eu.biz.DailyAudit.mapper.*;
import com.hooya.fa.eu.biz.DailyAudit.service.dateAggregation_02.CommonService;
import com.xxl.job.core.context.XxlJobHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class StockList {

	@Autowired
	private DailyStkOrigDataCollectMapper dailyStkOrigDataCollectMapper;

	@Autowired
	private DailyMetaExchangePlMapper dailyMetaExchangePlMapper;

	@Autowired
	private DailyTempKcjlDailyMapper dailyTempKcjlDailyMapper;

	@Autowired
	private DailyMetaWarehouseMapper dailyMetaWarehouseMapper;

	@Autowired
	private CommonService commonService;

	/**
	 * 主方法
	 */
	public void stockList(String currentDate) {
		try {

			log.info("StockList开始执行");

			// 计算结束日期
			String[] split = currentDate.split("-");
			if (split.length != 3) {
				log.error("日期格式有误！");
				return;
			}
			String year = split[0];
			String month = split[1];
			String day = split[2];

			List<StockListDTO> origData = unitData(currentDate);

			Map<String, List<StockListDTO>> stringListMap = dealPrice(origData);
			List<StockListDTO> priceData = stringListMap.get("priceData");
			List<StockListDTO> noPriceData = stringListMap.get("noPriceData");

			if (!noPriceData.isEmpty()) {
				log.error("有数据为空,数据为{}", noPriceData);
				throw new RuntimeException("有数据为空");
			}

			List<StockListDTO> stockData = dealStockQty(priceData, currentDate);

			List<StockListDTO> whNameData = dealWarehouseName(stockData);
			List<StockListDTO> inoutData = dealDirection(whNameData);
			List<StockListDTO> lastData = dealTypeQty(inoutData);
			List<StockListDTO> kcData = getKc(currentDate);

			List<StockListDTO> AllData = new ArrayList<>(lastData);
			AllData.addAll(kcData);

			// 创建输出目录
			String dir = "./stocklist/" + year + "/" + month + "/" + day;
			commonService.createDirectories(dir);

			// 按 belongs 分组并导出到 Excel
			exportDataToExcel(dir, AllData, year, month, day);

			log.info("StockList执行成功");
			XxlJobHelper.log("StockList执行成功");
		} catch (Exception e) {
			log.error("处理StockList数据时发生错误", e);
			XxlJobHelper.log("处理StockList数据时发生错误");
			throw new RuntimeException("处理StockList数据时发生错误", e);
		}
	}

	private List<StockListDTO> getKc(String currentDate) {
		String[] belongs = {"costway-fr", "costway-it", "costway-de", "costway-pl"};
		List<StockListDTO> result = new ArrayList<>();
		for (String belong : belongs) {
			List<String> order = dailyStkOrigDataCollectMapper.getSkuByBelong(belong, currentDate);
			List<StockListDTO> kc = dailyStkOrigDataCollectMapper.getDataByBelong(currentDate, belong);
			kc.forEach(f -> f.setDate(currentDate));
			List<StockListDTO> newkc = kc.stream().filter(f -> !order.contains(f.getSku())).collect(Collectors.toList());
			result.addAll(newkc);
		}
		return result;
	}

	/**
	 * 整合所有原始数据
	 */
	public List<StockListDTO> unitData(String currentDate) {
		String beforeDate = commonService.getPrevDate(currentDate);
		List<StockListDTO> b2bData = dailyStkOrigDataCollectMapper.getB2bData(currentDate);
		b2bData.forEach(f -> f.setExchangedate(beforeDate));

		List<StockListDTO> b2cData = dailyStkOrigDataCollectMapper.getB2cData(currentDate);
		b2cData.forEach(f -> f.setExchangedate(commonService.getPrevDate(f.getInvoiceDate())));

		List<StockListDTO> bsData = dailyStkOrigDataCollectMapper.getBsData(currentDate);
		bsData.forEach(f -> f.setExchangedate(commonService.getPrevDate(f.getInOutDate())));

		List<StockListDTO> cgData = dailyStkOrigDataCollectMapper.getCgData(currentDate);
		cgData.forEach(f -> f.setExchangedate(commonService.getPrevDate(f.getInvoiceDate())));

		List<StockListDTO> thData = dailyStkOrigDataCollectMapper.getThData(currentDate);
		thData.forEach(f -> f.setExchangedate(commonService.getPrevDate(f.getInvoiceDate())));

		List<StockListDTO> zyData = dailyStkOrigDataCollectMapper.getZyData(currentDate);
		zyData.forEach(f -> f.setExchangedate(commonService.getPrevDate(f.getInvoiceDate())));

		List<StockListDTO> origData = new ArrayList<>();
		origData.addAll(b2bData);
		origData.addAll(b2cData);
		origData.addAll(bsData);
		origData.addAll(cgData);
		origData.addAll(thData);
		origData.addAll(zyData);

		origData.forEach(f -> {
			f.setDate(currentDate);
			f.setInvoiceNumber(f.getInvoiceno());
		});

		return origData;
	}

	/**
	 * 处理价格和汇率
	 */
	public Map<String, List<StockListDTO>> dealPrice(List<StockListDTO> data) {
		Map<String, List<StockListDTO>> result = new HashMap<>();

		// 获取汇率数据
		List<StockListDTO> exchangeList = dailyMetaExchangePlMapper.getDataForStockList();

		List<StockListDTO> noPriceData = data.stream()
				.filter(dto -> dto.getPrice() == null)
				.collect(Collectors.toList());

		data.forEach(dto -> {
			if (dto.getPrice() != null && dto.getQty() != null) {
				dto.setTotalcost(dto.getPrice() * dto.getQty());
			} else {
				dto.setTotalcost(0.0);
			}
		});

		List<StockListDTO> eurData = data.stream().filter(f -> "EUR".equals(f.getCurrency())).collect(Collectors.toList());
		if (!eurData.isEmpty()) {
			Map<String, List<StockListDTO>> descriptionDataMap = exchangeList.stream().collect(Collectors.groupingBy(StockListDTO::getRatedate));
			List<StockListDTO> withDescription = new ArrayList<>();
			for (StockListDTO mainItem : eurData) {
				String key = mainItem.getExchangedate();
				if (descriptionDataMap.containsKey(key)) {
					List<StockListDTO> StockListDTOS = descriptionDataMap.get(key);
					StockListDTOS.forEach(f -> {
						StockListDTO newItem = new StockListDTO();
						BeanUtil.copyProperties(mainItem, newItem);
						newItem.setEurplnrate(f.getEurplnrate());
						newItem.setUsdplnrate(f.getUsdplnrate());
						newItem.setUsdeurrate(f.getUsdeurrate());
						newItem.setExistflag(f.getExistflag());
						newItem.setUnitPricePln((newItem.getPrice() == null ? 0.0 : newItem.getPrice()) * (newItem.getEurplnrate() == null ? 0.0 : newItem.getEurplnrate()));
						newItem.setCurrencyRate(f.getEurplnrate());
						newItem.setUnitPriceEur(newItem.getPrice());
						withDescription.add(newItem);
					});
				} else {
					withDescription.add(mainItem);
				}
			}
			eurData = withDescription;
		}

		List<StockListDTO> usdData = data.stream().filter(f -> "USD".equals(f.getCurrency())).collect(Collectors.toList());
		if (!usdData.isEmpty()) {
			Map<String, List<StockListDTO>> descriptionDataMap = exchangeList.stream().collect(Collectors.groupingBy(StockListDTO::getRatedate));
			List<StockListDTO> withDescription = new ArrayList<>();
			for (StockListDTO mainItem : usdData) {
				String key = mainItem.getExchangedate();
				if (descriptionDataMap.containsKey(key)) {
					List<StockListDTO> StockListDTOS = descriptionDataMap.get(key);
					StockListDTOS.forEach(f -> {
						StockListDTO newItem = new StockListDTO();
						BeanUtil.copyProperties(mainItem, newItem);
						newItem.setEurplnrate(f.getEurplnrate());
						newItem.setUsdplnrate(f.getUsdplnrate());
						newItem.setUsdeurrate(f.getUsdeurrate());
						newItem.setExistflag(f.getExistflag());
						newItem.setUnitPricePln((newItem.getPrice() == null ? 0.0 : newItem.getPrice()) * (newItem.getUsdplnrate() == null ? 0.0 : newItem.getUsdplnrate()));
						newItem.setCurrencyRate(newItem.getUsdplnrate());
						newItem.setUnitPriceUSD(newItem.getPrice());
						withDescription.add(newItem);
					});
				} else {
					withDescription.add(mainItem);
				}
			}
			usdData = withDescription;
		}

		List<StockListDTO> plnData = data.stream().filter(f -> "PLN".equals(f.getCurrency())).collect(Collectors.toList());
		if (!plnData.isEmpty()) {
			plnData.forEach(f -> f.setUnitPricePln(f.getPrice()));
		}

		List<StockListDTO> addExchangeData = new ArrayList<>(eurData);
		addExchangeData.addAll(usdData);
		addExchangeData.addAll(plnData);

		result.put("priceData", addExchangeData);
		result.put("noPriceData", noPriceData);
		return result;
	}

	/**
	 * 处理库存数量
	 */
	public List<StockListDTO> dealStockQty(List<StockListDTO> data, String currentDate) {
		String preMonthEnd = commonService.getPrevDate(currentDate);

		List<StockListDTO> beginQty = dailyTempKcjlDailyMapper.getBeginQty_StockList(preMonthEnd);
		List<StockListDTO> endQty = dailyTempKcjlDailyMapper.getEndQty_StockList(currentDate);

		Map<String, List<StockListDTO>> beginQtyDataMap = beginQty.stream().collect(Collectors.groupingBy(f -> f.getSku() + f.getWhId() + f.getBelongs()));
		List<StockListDTO> addBeginStock = new ArrayList<>();
		for (StockListDTO mainItem : data) {
			String key = mainItem.getSku() + mainItem.getWhId() + mainItem.getBelongs();
			if (beginQtyDataMap.containsKey(key)) {
				List<StockListDTO> StockListDTOS = beginQtyDataMap.get(key);
				StockListDTOS.forEach(f -> {
					StockListDTO newItem = new StockListDTO();
					BeanUtil.copyProperties(mainItem, newItem);
					newItem.setBeginqty(f.getBeginqty());
					addBeginStock.add(newItem);
				});
			} else {
				addBeginStock.add(mainItem);
			}
		}

		Map<String, List<StockListDTO>> endQtyDataMap = endQty.stream().collect(Collectors.groupingBy(f -> f.getSku() + f.getWhId() + f.getBelongs()));
		List<StockListDTO> addEndStock = new ArrayList<>();
		for (StockListDTO mainItem : addBeginStock) {
			String key = mainItem.getSku() + mainItem.getWhId() + mainItem.getBelongs();
			if (endQtyDataMap.containsKey(key)) {
				List<StockListDTO> StockListDTOS = endQtyDataMap.get(key);
				StockListDTOS.forEach(f -> {
					StockListDTO newItem = new StockListDTO();
					BeanUtil.copyProperties(mainItem, newItem);
					newItem.setEndqty(f.getEndqty());
					addEndStock.add(newItem);
				});
			} else {
				addEndStock.add(mainItem);
			}
		}

		addEndStock.forEach(f -> {
			f.setStockBeginOfMonth(f.getBeginqty());
			f.setStockEndOfMonth(f.getEndqty());
		});

		return addEndStock;
	}

	/**
	 * 处理仓库名称
	 */
	public List<StockListDTO> dealWarehouseName(List<StockListDTO> data) {
		List<StockListDTO> whNameData = dailyMetaWarehouseMapper.getData();

		Map<String, List<StockListDTO>> descriptionDataMap = whNameData.stream().collect(Collectors.groupingBy(StockListDTO::getWhId));
		List<StockListDTO> withDescription = new ArrayList<>();
		for (StockListDTO mainItem : data) {
			String key = mainItem.getWhId();
			if (descriptionDataMap.containsKey(key)) {
				List<StockListDTO> StockListDTOS = descriptionDataMap.get(key);
				StockListDTOS.forEach(f -> {
					StockListDTO newItem = new StockListDTO();
					BeanUtil.copyProperties(mainItem, newItem);
					newItem.setWhName(f.getWhName());
					withDescription.add(newItem);
				});
			} else {
				withDescription.add(mainItem);
			}
		}

		return withDescription;
	}

	/**
	 * 处理出入库方向
	 */
	public List<StockListDTO> dealDirection(List<StockListDTO> data) {
		// TODO -- 可能会出现问题 由于数据列的关系--py中独有的内容
		List<StockListDTO> inData = data.stream().filter(f -> "in".equals(f.getDirection())).collect(Collectors.toList());
		inData.forEach(f -> {
			f.setInboundQty(f.getQty());
			f.setInCostNet(f.getTotalcost());
			f.setInPriceNetEur("EUR".equals(f.getCurrency()) ? f.getUnitPriceEur() : null);
			f.setInPriceNetUsd("USD".equals(f.getCurrency()) ? f.getUnitPriceUSD() : null);
			f.setInPriceNetPln("PLN".equals(f.getCurrency()) ? f.getUnitPricePln() : null);
		});

		List<StockListDTO> outData = data.stream().filter(f -> "out".equals(f.getDirection())).collect(Collectors.toList());
		outData.forEach(f -> {
			f.setOutboundQty(f.getQty());
			f.setOutRevenueNet(f.getTotalcost());
			f.setOutPriceNetEur("EUR".equals(f.getCurrency()) ? f.getUnitPriceEur() : null);
			f.setOutPriceNetUsd("USD".equals(f.getCurrency()) ? f.getUnitPriceUSD() : null);
			f.setOutPriceNetPln("PLN".equals(f.getCurrency()) ? f.getUnitPricePln() : null);
		});

		List<StockListDTO> inoutData = new ArrayList<>(inData);
		inoutData.addAll(outData);
		inoutData.forEach(f -> {
			f.setUnitPriceEur("EUR".equals(f.getCurrency()) ? f.getUnitPriceEur() : null);
			f.setCurrencyRate("EUR".equals(f.getCurrency()) ? f.getCurrencyRate() : null);
		});

		return inoutData;
	}

	/**
	 * 处理类型和数量
	 */
	public List<StockListDTO> dealTypeQty(List<StockListDTO> data) {
		return data.stream().peek(item -> {

			String type = item.getType();
			Integer qty = item.getQty();

			// 处理报损和退货
			if ("报损".equals(type) || "退货".equals(type)) {
				item.setInventoryLossIncome(qty);
			}

			// 处理转运
			if ("转运".equals(type)) {
				item.setTransferBetweenWarehouses(qty);
				// 转运类型不需要发票日期
				item.setInvoiceDate(null);
			}

			// 处理B2C
			if ("B2C".equals(type)) {
				item.setB2c(qty);
			}

			// 处理B2B
			if ("B2B".equals(type)) {
				item.setB2b(qty);
			}

			// 处理退货类型不需要发票日期
			if ("退货".equals(type)) {
				item.setInvoiceDate(null);
			}

			// java中不需要转null值，所以这里也不需要回转为null
			// 处理转运类型的bor_inv
			if (!"转运".equals(type)) {
				item.setBorInv(null);
			}

		}).collect(Collectors.toList());
	}

	/**
	 * 按 belongs 分组并导出到 Excel
	 *
	 * @param data  数据列表
	 * @param year  年份
	 * @param month 月份
	 */
	private void exportDataToExcel(String dir, List<StockListDTO> data, String year, String month, String day) {
		try {
			// 按 belongs 分组
			Map<String, List<StockListDTO>> groupedData = data.stream()
					.collect(Collectors.groupingBy(StockListDTO::getBelongs));

			for (Map.Entry<String, List<StockListDTO>> entry : groupedData.entrySet()) {
				String belong = entry.getKey();
				List<StockListDTO> groupData = entry.getValue();

				// 创建文件路径
				String fileDir = dir + "/" + belong + "-" + year + month + day;
				String fileName = String.format(fileDir + ".xlsx");

				// 处理空值数据
				handleData(groupData);

				// 使用EasyExcel写入文件
				writeExcelWithEasyExcel("stockList-" + year + "-" + month + "-" + day, groupData, fileName);
			}
			log.info("数据已成功导出到Excel文件");
		} catch (Exception e) {
			log.error("导出Excel文件失败", e);
			throw new RuntimeException("导出Excel文件失败", e);
		}
	}

	/**
	 * 处理空值数据
	 */
	private void handleData(List<StockListDTO> Data) {
		Data.forEach(f -> {
//            f.setDate(f.getDate() != null ? f.getDate() : "");
//            f.setWhId(f.getWhId() != null ? f.getWhId() : "");
//            f.setWhName(f.getWhName() != null ? f.getWhName() : "");
//            f.setSku(f.getSku() != null ? f.getSku() : "");
			f.setStockBeginOfMonth(f.getStockBeginOfMonth() != null ? f.getStockBeginOfMonth() : 0);
			f.setStockEndOfMonth(f.getStockEndOfMonth() != null ? f.getStockEndOfMonth() : 0);
//            f.setInOutDate(f.getInOutDate() != null ? f.getInOutDate() : "");
//            f.setInboundQty(f.getInboundQty() != null ? f.getInboundQty() : 0);
//            f.setInPriceNetEur(f.getInPriceNetEur() != null ? f.getInPriceNetEur() : 0.0);
//            f.setInPriceNetUsd(f.getInPriceNetUsd() != null ? f.getInPriceNetUsd() : 0.0);
//            f.setInPriceNetPln(f.getInPriceNetPln() != null ? f.getInPriceNetPln() : 0.0);
//            f.setInCostNet(f.getInCostNet() != null ? f.getInCostNet() : 0.0);
//            f.setOutboundQty(f.getOutboundQty() != null ? f.getOutboundQty() : 0);
//            f.setOutPriceNetEur(f.getOutPriceNetEur() != null ? f.getOutPriceNetEur() : 0.0);
//            f.setOutPriceNetUsd(f.getOutPriceNetUsd() != null ? f.getOutPriceNetUsd() : 0.0);
//            f.setOutPriceNetPln(f.getOutPriceNetPln() != null ? f.getOutPriceNetPln() : 0.0);
//            f.setOutRevenueNet(f.getOutRevenueNet() != null ? f.getOutRevenueNet() : 0.0);
//            f.setB2b(f.getB2b() != null ? f.getB2b() : 0);
//            f.setB2c(f.getB2c() != null ? f.getB2c() : 0);
//            f.setTransferBetweenWarehouses(f.getTransferBetweenWarehouses() != null ? f.getTransferBetweenWarehouses() : 0);
//            f.setBorInv(f.getBorInv() != null ? f.getBorInv() : "");
//            f.setInvoiceNumber(f.getInvoiceNumber() != null ? f.getInvoiceNumber() : "");
//            f.setInvoiceDate(f.getInvoiceDate() != null ? f.getInvoiceDate() : "");
//            f.setUnitPriceEur(f.getUnitPriceEur() != null ? f.getUnitPriceEur() : 0.0);
//            f.setCurrencyRate(f.getCurrencyRate() != null ? f.getCurrencyRate() : 0.0);
//            f.setUnitPricePln(f.getUnitPricePln() != null ? f.getUnitPricePln() : 0.0);
//            f.setSeller(f.getSeller() != null ? f.getSeller() : "");
//            f.setBuyer(f.getBuyer() != null ? f.getBuyer() : "");
//            f.setInventoryLossIncome(f.getInventoryLossIncome() != null ? f.getInventoryLossIncome() : 0);
//            f.setBelongs(f.getBelongs() != null ? f.getBelongs() : "");
		});
	}

	/**
	 * 使用EasyExcel写入Excel文件
	 *
	 * @param sheetName sheet名称
	 * @param groupData 分组数据
	 * @param fileName  文件名
	 */
	private void writeExcelWithEasyExcel(String sheetName, List<StockListDTO> groupData, String fileName) {
		try {
			// 将StockListDTO转换为StockListExcelDTO
			List<StockListExcelDTO> excelData = groupData.stream().map(item -> {
				StockListExcelDTO excelItem = new StockListExcelDTO();
				BeanUtil.copyProperties(item, excelItem);
				return excelItem;
			}).collect(Collectors.toList());

			// 使用EasyExcel写入文件
			EasyExcel.write(fileName, StockListExcelDTO.class)
					.sheet(sheetName)
					.doWrite(excelData);

			log.info("数据已成功写入Excel文件: {}", fileName);
		} catch (Exception e) {
			log.error("写入Excel文件失败: {}", fileName, e);
			throw new RuntimeException("写入Excel文件失败: " + fileName, e);
		}
	}

}